package com.ezlcp.form.service;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ezlcp.commons.base.db.BaseDao;
import com.ezlcp.commons.base.db.BaseService;
import com.ezlcp.commons.constant.Constants;
import com.ezlcp.commons.constant.StatusEnum;
import com.ezlcp.commons.dto.Datasource;
import com.ezlcp.commons.service.impl.SuperServiceImpl;
import com.ezlcp.commons.tool.StringUtils;
import com.ezlcp.commons.utils.ContextUtil;
import com.ezlcp.commons.utils.NacosUtils;
import com.ezlcp.form.mapper.DatasourceMapper;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

import static com.ezlcp.commons.constant.Constants.*;

/**
 * [自定义的数据库连接]业务服务类
 */
@Service
public class DatasourceServiceImpl extends SuperServiceImpl<DatasourceMapper, Datasource> implements BaseService<Datasource> {

    @Resource
    private DatasourceMapper datasourceMapper;

    @Lazy
    @Resource
    private NacosUtils nacosUtils;


    /***
     * @description 选择数据源
     * @param moduleId 模块ID
     * @return java.util.List<com.ezlcp.commons.dto.Datasource>
     * @author Elwin ZHANG
     * @date 2023/6/15 13:55
     */
    public List<Datasource> selectDataSource(String moduleId) {
        String tenantId = ContextUtil.getCurrentTenantId();
        //初始化默认数据源
        List<Datasource> dataSources = new ArrayList<>();
        Datasource ds = new Datasource();
        ds.setDsId("");
        ds.setDsName("default");
        dataSources.add(ds);

        QueryWrapper<Datasource> wrapper = new QueryWrapper<>();
        wrapper.select(COL_DS_ID, COL_DS_NAME);
        if (StringUtils.isEmpty(tenantId)) {
            wrapper.and(query -> query.eq(COL_TENANT_ID, "").or().isNull(COL_TENANT_ID));
        } else {
            wrapper.eq(COL_TENANT_ID, tenantId);
        }
        //当前模块的、或共享的数据源
        wrapper.and(query -> query.eq(COL_MODULE_ID, moduleId).or().eq(COL_IS_PUBLIC, 1));
        wrapper.eq(COL_STATUS, StatusEnum.enable.getCode());
        wrapper.orderByDesc(COL_CREATE_TIME);
        //默认数据源合并查询结果
        var data = this.datasourceMapper.selectList(wrapper);
        if (data != null) {
            dataSources.addAll(data);
        }
        return dataSources;

    }

    /***
     * @description 将所有的数据源更新到Nacos上
     * @author Elwin ZHANG
     * @date 2023/6/7 14:38
     */
    @SneakyThrows
    public void pushAll2Nacos() {
        var list = this.getAll();
        if (list == null || list.size() == 0) {
            return;
        }
        String config = JSON.toJSONString(list);
        var service = nacosUtils.getConfigService("");
        service.publishConfig(NacosUtils.KEY_OF_DATASOURCE, "", config);
        nacosUtils.closeService(service);
    }


    /***
     * @description 逻辑删除数据源
     * @param dsId 数据源ID
     * @author Elwin ZHANG
     * @date 2023/5/30 15:18
     */
    public void delDataSource(String dsId) {
        var ds = this.datasourceMapper.selectById(dsId);
        if (ds == null) {
            return;
        }
        ds.setStatus((short) StatusEnum.deleted.getValue());
        ds.setSeq(ds.getSeq() + 1);
        this.datasourceMapper.updateById(ds);
    }

    /***
     * @description 检查Key是否存在
     * @param identifier key
     * @param dsId 当前记录ID
     * @return boolean
     * @author Elwin ZHANG
     * @date 2023/5/17 16:04
     */
    public boolean checkKeyRepeat(String identifier, String dsId) {
        QueryWrapper<Datasource> wrapper = new QueryWrapper();
        String tenantId = ContextUtil.getCurrentTenantId();
        if (StringUtils.isNotEmpty(tenantId)) {
            wrapper.eq(Constants.COL_TENANT_ID, tenantId);
        } else {
            wrapper.and(query -> query.eq(COL_TENANT_ID, "").or().isNull(COL_TENANT_ID));
        }
        wrapper.lambda().eq(Datasource::getIdentifier, identifier).
                lt(Datasource::getStatus, StatusEnum.deleted.getValue());
        if (StringUtils.isNotEmpty(dsId)) {
            wrapper.lambda().ne(Datasource::getDsId, dsId);
        }
        var cnt = this.datasourceMapper.selectCount(wrapper);
        if (cnt != null && cnt > 0) {
            return true;
        }
        return false;
    }

    @Override
    public BaseDao<Datasource> getRepository() {
        return datasourceMapper;
    }
}